/**
 * @author Federico Consoli
 *
 * Released under GNU GPLv3 (http://www.gnu.org/licenses/gpl-3.0.txt)
 */

#include "Service_2.h"

using namespace std;

Service_2::valori* Service_2::find_elem(string name) {
    list_val*elem = testa;
    while (elem) {
        if (elem->elem->str[0] == name)
            return elem->elem;
        elem = elem->succ;
    }
    return 0;
}

Service_2::Service_2(string nuovo_ip, unsigned short nuovo_porta_base, string name_of_service) {
    cout << display() + "Building service 2... ";
    testa = 0;
    lista_img = "";
    ip = nuovo_ip;
    porta_base = nuovo_porta_base;
    name = name_of_service;
    cout << "Done\n";
}

Service_2::~Service_2() {
    list_val*temp = testa;
    cout << display() + "Closing services 2...\n";
    while (temp) {
        testa = testa->succ;
        delete [] temp->elem->str;
        delete [] temp->elem->bufflen;
        delete [] temp->elem->buffer[0];
        delete [] temp->elem->buffer;
        delete temp->elem;
        delete temp;
        temp = testa;
    }
    cout << display() + "Services 2 closed...\n";
}

void Service_2::salva() {
    RW.leggi_begin();
    list_val*elem = testa;
    while (elem) {
        cout << display() + "Saving image from buffer to the disk... " + elem->elem->str[0] + '\n';
        Connection::string_to_file(elem->elem->buffer[0], elem->elem->str[0], elem->elem->bufflen[0]);
        cout << display() + "Image " + elem->elem->str[0] + " saved to the disk\n";
        elem = elem->succ;
    }
    RW.leggi_end();
}

void Service_2::menu(Server*registro_locale) {
    registro_locale->name = name;
    int quit = 0;
    int all = 0;
    int scelta;
    int num_serv;
    while (!quit) {
        cout << "\n--------------- [SERVICE 2 - MENU] ---------------" << endl;
        cout << "0 - Exit\n";
        cout << "1 - Register Service" << endl;
        cout << "2 - Unregister service" << endl;
        cout << "3 - Lists the services available" << endl;
        cout << "4 - Save images from the buffer on the hard drive" << endl;
        cout << "5 - Lists the images in the buffer" << endl;
        cout << "--------------- [SERVICE 2 - MENU] ---------------" << endl;
        cout << "> ";
        cin >> scelta;
        switch (scelta) {
            case 0:
                registro_locale->deregistrati();
                quit = 1;
                break;
            case 1:
                cout << "\n-> Enter the number of the service function to record\n";
                cout << "-> Press 0 to register all services\n> ";
                cin >> num_serv;
                if (num_serv == 0) {
                    all = 1;
                    num_serv = 1;
                }
                switch (num_serv) {

                    case 1:
                        registro_locale->registra_servizio("Get list", "", "", ip, porta_base);
                        num_serv = 2;
                        if (!all) break;
                    case 2:
                        registro_locale->registra_servizio("Store image", "string buffer", "", ip, porta_base + 1);
                        num_serv = 3;
                        if (!all) break;
                    case 3:
                        registro_locale->registra_servizio("Get image", "string", "buffer", ip, porta_base + 2);
                        break;
                    default:
                        cout << "Unrecognized function number\n";
                        break;
                }
                break;
            case 2:
                cout << "-> Enter the number of the service function to unregister\n";
                cout << "-> Press 0 to unregister all services\n";
                cin >> num_serv;
                if (num_serv == 0)
                    registro_locale->deregistrati();
                else if (num_serv == 1)
                    registro_locale->deregistra_servizio("Get list", ip, porta_base);
                else if (num_serv == 2)
                    registro_locale->deregistra_servizio("Store image", ip, porta_base + 1);
                else if (num_serv == 3)
                    registro_locale->deregistra_servizio("Get image", ip, porta_base + 2);
                else
                    cout << "Unrecognized function number\n";
                break;
            case 3:
                cout << "\nServices available are:\n";
                cout << "1. Get list, on ip " << ip << " and port " << porta_base << endl;
                cout << "2. Store image, on ip " << ip << " and port " << porta_base + 1 << endl;
                cout << "3. Get image, on ip " << ip << " and port " << porta_base + 2 << "\n\n";
                break;
            case 4:
                salva();
                break;
            case 5:
                RW.leggi_begin();
                cout << "Image in the buffer are: '" +lista_img + "' \n";
                RW.leggi_end();
                break;
            
            default:
                cout << "Unrecognized command number\n";
                break;
        }
    }
}

int Service_2::store(Response *R, int sd) {
    size_t found;
    Response::valori*val_in = R->ricevi_pacchetto(sd, "in");
    cout << display() + "Store image of -> " + val_in->str[0] + " started\n";
    RW.scrivi_begin();
    //La ricerca e' da fare in mutua esclusione
    found = lista_img.find(val_in->str[0]);
    //Se trovi qualcosa vuol dire che l'immagine e' già presente
    if (found != string::npos) {
        Response::valori*trova = find_elem(val_in->str[0]);
        trova->bufflen[0] = val_in->bufflen[0];
        delete [] trova->buffer[0];
        trova->buffer[0] = val_in->buffer[0];
        Connection::send_s("Image " + val_in->str[0] + " present and rewritten", sd);
        RW.scrivi_end();
        cout << display() + "Store image of -> " + val_in->str[0] + " finished, image has been rewritten\n";
        delete []val_in->bufflen;
        delete []val_in->str;
        delete []val_in->buffer;
        delete val_in;
        return 0;
    }        //Tutto l'else e' da fare in mutua esclusione
    else {
        lista_img.append(val_in->str[0]);
        lista_img.append(1, ' ');
        list_val*new_elem = new list_val;
        new_elem->succ = testa;
        new_elem->elem = val_in;
        testa = new_elem;
        //Inutile creare un pacchetto di uscita per una string
        Connection::send_s("Image " + val_in->str[0] + "has been uploaded successfully", sd);
        RW.scrivi_end();
        cout << display() + "Store image of -> " + val_in->str[0] + " finished, image has been stored\n";
        return 0;
    }
}

int Service_2::get_img(Response *R, int sd) {
    size_t found;
    Response::valori*val_in = R->ricevi_pacchetto(sd, "in");
    cout << display() + "Get Image of -> " + val_in->str[0] + " started\n";
    RW.leggi_begin();
    found = lista_img.find(val_in->str[0]);
    //Se trovi qualcosa vuol dire che l'immagine e' già presente
    if (found != string::npos) {
        Response::valori*trova = find_elem(val_in->str[0]);
        Connection::send_s("Found", sd);
        R->invia_pacchetto(trova, sd, "out");
        RW.leggi_end();
        cout << display() + "Get Image of -> " + val_in->str[0] + " finished\n";
        R->rem_val(val_in, "in");
        return 0;
    } else {
        RW.leggi_end();
        Connection::send_s("Not found", sd);
        cout << display() + "Get Image of -> " + val_in->str[0] + " finish, but image not found\n";
        R->rem_val(val_in, "in");
        return 1;
    }
}

int Service_2::get_list(int sd) {
    cout << display() + "Get list started\n";
    //Inutile creare un pacchetto di uscita per una string
    RW.leggi_begin();
    Connection::send_s(lista_img, sd);
    RW.leggi_end();
    cout << display() + "Get list done\n";
    return 0;
}